#include "Tuplets.h"
namespace SymCe{
	Tuplet * childs_to_tuplets(OperatorType oper, ListOfChilds * childs){
		Tuplet * to_return = NULL;
		/* This function is not supposed to bother with numbers!
		//Numbers first!
		Number numbers;
		bool nums_used = false;
		ListOfChilds * nums;
		if(oper == MULTIPLY){
			numbers = 1;
			while (childs->subtree->symbol.type == NUMBER){
				if(childs->inverted){
					//TODO:: Division by zero!!
					numbers = numbers/childs->subtree->symbol.number;
				}else{
					numbers = numbers*childs->subtree->symbol.number;
				}
				childs = childs->next;
			}
			if(numbers != 1){
				nums = new ListOfChilds;
				nums->inverted = false;
				nums->subtree = new Multitree;
				nums->subtree->childs = NULL;
				nums->subtree->symbol.type = NUMBER;
				nums->subtree->symbol.number = numbers;
				nums->next = childs;
				childs = nums;
			}
		}else{
			numbers = 0;
			while (childs->subtree->symbol.type == NUMBER){
				if(childs->inverted){
					numbers = numbers-childs->subtree->symbol.number;
				}else{
					numbers = numbers+childs->subtree->symbol.number;
				}
				childs = childs->next;
			}
			if(numbers != 0){
				nums_used = true;
				nums = new ListOfChilds;
				nums->inverted = false;
				nums->subtree = new Multitree;
				nums->subtree->childs = NULL;
				nums->subtree->symbol.type = NUMBER;
				nums->subtree->symbol.number = numbers;
				nums->next = childs;
				childs = nums;
			}
		}*/

		while(childs != NULL){
			Tuplet * added = new Tuplet;
			added->tree = copy_tree(childs->subtree);
			//Copy tree to added. If it is a tree, that needs anything done to it, then do it.

			//If we have multiplication, then if there is tree a^b and b is number, then do something.
			if(oper == MULTIPLY){
				if((added->tree->symbol.type == OPERATOR)
					&& (added->tree->symbol.oper == POWER)
					&& (added->tree->childs->next->subtree->symbol.type == NUMBER)){//Second child of current tree is number
						//Do not copy
						Multitree * a = added->tree->childs->subtree; //This is rest.
						Multitree * b = added->tree->childs->next->subtree;
						//assert(b->symbol.type == NUMBER);
						if (childs->inverted){
							added->coefficient = -(b->symbol.number);
						}else{
							added->coefficient = b->symbol.number;
						}
						//delete first node of added (with listofchilds) and replace added with a.
						delete added->tree->childs->next;
						delete added->tree->childs;
						delete added->tree;
						added->tree = a;
						//We do not need b anymore. Since it is leaf...
						delete b;
				}else{
					//else just set coefficient to 1 or -1
					if (childs->inverted){
						added->coefficient = -1;
					}else{
						added->coefficient = 1;
					}
				}
			}else{
				//assert(oper == PLUS);
				//Similar to previous. However, now multiplication is operator that concerns us.
				//Let the coeff. be 1 or -1 and then "edit" it.
				if(childs->inverted){
					added->coefficient = -1;
				}else{
					added->coefficient = 1;
				}
				//If child is multiplication, that has number (since tree is sorted, the number would be first)
				if((added->tree->symbol.type == OPERATOR)
					&& (added->tree->symbol.oper == MULTIPLY)
					&& (added->tree->childs->subtree->symbol.type == NUMBER)){
						//Remove number (first child) from added.
						ListOfChilds * first = added->tree->childs;
						added->tree->childs = added->tree->childs->next;
						
						//Now coefficient depends on added->tree->childs->inverted.
						if(first->inverted){ // for example in x/2, the coefficient should be 1/2, not 2
							added->coefficient = added->coefficient / first->subtree->symbol.number;
						}else{
							added->coefficient = added->coefficient * first->subtree->symbol.number;
						}
						delete first->subtree; //It is number, so it is leaf
						//first->next is now added->tree->childs.
						delete first;
						first = NULL;
						//if tree is now multiplication with only one operand, then if it is not inverted, then pull it out.
						if((added->tree->childs->next == NULL) && (!(added->tree->childs->inverted))){
							Multitree * a = added->tree->childs->subtree;
							delete added->tree->childs;
							delete added->tree;
							added->tree = a;
						}
						//It should be done!
				}
			}
			added->next = to_return;
			to_return = added;
			childs = childs->next;
		}
/*		if(nums_used){
			delete nums->subtree;
			delete nums;
		}*/
		return to_return;
	}

	Tuplet * add_tuplets(Tuplet * tuplet){
		Tuplet * to_return = NULL;
		while(tuplet != NULL){
			Tuplet * pass = to_return;
			while((pass != NULL) && (treecmp(pass->tree, tuplet->tree))){
				pass = pass->next;
			}
			if (pass != NULL){
				pass->coefficient = pass->coefficient + tuplet->coefficient;
			}else{
				pass = new Tuplet;
				pass->coefficient = tuplet->coefficient;
				pass->tree = copy_tree(tuplet->tree);
				pass->next = to_return;
				to_return = pass;
			}
			tuplet = tuplet->next;
		}
		return to_return;
	}

	void delete_tuplets(Tuplet * tuplet){
		if(tuplet == NULL){
			return;
		}else{
			delete_tuplets(tuplet->next);
			delete_tree(tuplet->tree);
			delete tuplet;
		}
	}

	Tuplet * remove_null_tuplets(Tuplet * tuplet){
		Tuplet * to_return = NULL;
		while(tuplet != NULL){
			if(tuplet->coefficient != 0){
				Tuplet * added = new Tuplet;
				added->coefficient = tuplet->coefficient;
				added->tree = copy_tree(tuplet->tree);
				added->next = to_return;
				to_return = added;
			}
			tuplet = tuplet->next;
		}
		return to_return;
	}

	ListOfChilds * tuplets_to_childs(OperatorType oper, Tuplet * tuplet){
		//converts tuplets back to list of childs.
		ListOfChilds *to_return = NULL;
		ListOfChilds * added = NULL;
		while(tuplet != NULL){
			added = new ListOfChilds;
			if((tuplet->coefficient == 1) || (tuplet->coefficient == -1)){
				added->subtree = copy_tree(tuplet->tree);
				added->inverted = (tuplet->coefficient == -1); //if coef. is -1, then it is inverted.
			}else{
				Number ncoef;
				if(tuplet->coefficient < 0){
					added->inverted = true;
					ncoef = - tuplet->coefficient;
				}else{
					added->inverted = false;
					ncoef = tuplet->coefficient;
				}
				Multitree * tree = copy_tree(tuplet->tree);
				Multitree * coef = new Multitree;
				coef->childs = NULL;
				coef->symbol.type = NUMBER;
				coef->symbol.number = ncoef;
				//and now we just somehow connect tree and coef.
				//How? It depends on oper. Is it PLUS or MULTIPLY?
				if(oper == PLUS){
					//If tree is multiplication, then add coef. to it as first child.
					if((tree->symbol.type == OPERATOR) && (tree->symbol.oper == MULTIPLY)){
						ListOfChilds * first = new ListOfChilds;
						first->inverted = false;
						first->subtree = coef;
						first->next = tree->childs;
						tree->childs = first;
						added->subtree = tree;
					}else{
						//Create multiply node and attach coef and tree as childs
						//Create multiply
						added->subtree = new Multitree;
						added->subtree->symbol.type = OPERATOR;
						added->subtree->symbol.oper = MULTIPLY;
						//Create two childs
						added->subtree->childs = new ListOfChilds;
						added->subtree->childs->next = new ListOfChilds;
						added->subtree->childs->next->next = NULL;
						//Second is tree
						added->subtree->childs->next->inverted = false;
						added->subtree->childs->next->subtree = tree;
						//First is coef
						added->subtree->childs->inverted = false;
						added->subtree->childs->subtree = coef;
					}
				}else{
					//oper == MULTIPLY
					//We just create POWER and attach coef and tree as sons.
					//Same as previous. Except for the order of sons!
					added->subtree = new Multitree;
					added->subtree->symbol.type = OPERATOR;
					added->subtree->symbol.oper = POWER;
					//Create two childs
					added->subtree->childs = new ListOfChilds;
					added->subtree->childs->next = new ListOfChilds;
					added->subtree->childs->next->next = NULL;
					//Second is coef.
					added->subtree->childs->next->inverted = false;
					added->subtree->childs->next->subtree = coef;
					//First is tree
					added->subtree->childs->inverted = false;
					added->subtree->childs->subtree = tree;
				}
			}//coefficient == +/- 1
			added->next = to_return;
			to_return = added;
			tuplet = tuplet->next;
		}
		return to_return;
	}

				






}




						

